package com.tedu.API.map;

import org.junit.Test;

import java.util.*;
import java.util.function.BiConsumer;

/**
 * 包位置 java.util
 * Map顶级映射接口
 * 作用：一个元素由两个对象构成：分别是Key和Value;
 * 保存一个元素：Kry-Value【保存一对：两个对象】
 * 用途：通常数据库搭配使用
 * 特点：键：无序，无下标，不可重复，实际上存HashSet
 * 值：存泛型约束的类型，可以重复，实际上存Collection
 * Map 接口对象创建---实现类
 * HashMap:[超级常用]  由键值对组成，使用哈希算法实现 键与值都可以为null 但键中值允许有一个null
 * LinkedHashMap:【不常用：方法和HashMap类似】
 * TreeMap: 【算法：红黑树】性能：较低 线程安全
 * HashTable: jdk1.0 由哈希算法实现，解决多线程问题
 * ConcurrentHashMap:【常用】 多线程
 */
public class MapAPI {
    @Test
    public void testMap() {
        //创建Map映射集合接口
        Map<Object, String> map = new HashMap<>();
        /**
         * put(键k,值v)  返回值：V  value---实际上Collection
         * 作用：映射集合当中存入一对元素，键与值
         */
        map.put("西游记", "孙悟空");  //key键:Set集合 ：无序，无下标，唯一
        map.put("红楼梦", "林黛玉"); //键值一样，进行覆盖
        map.put("水浒传", "宋公明");
        map.put("三国志", "曹孟德");
        map.put("红楼梦", "贾宝玉");
        map.put(null, "无名氏");
        map.put(null, "无名氏");
        System.out.println("Map集合" + map);

        //需求：获取一组元素中值：“林黛玉”  get(键) 通过键找到值
        String lin = map.get("红楼梦");
        System.out.println("通过键找值" + lin);
        //没有这个键，自动按照Collection对象，补对象默认:null
        System.out.println("通过键找值【键不存在】" + map.get("三国"));

        //删除元素中的键  remove(Key)  返回值 V value Collection
        map.remove("红楼梦");
        System.out.println("map集合" + map);

        //size() 获取映射集合的元素个数
        System.out.println("map的元素总数" + map.size());

        //containsKey() 判断键是否存在    返回值：boolean
        //containsValue()  判断我们的值是否存在   返回值：boolean
        boolean b = map.containsKey("三国志");
        System.out.println("判断键值是否存在" + b);
        boolean v = map.containsValue("宋公明");
        System.out.println("判断值是否存在" + v);
        System.out.println("不存在" + map.containsValue("张孟涛"));
    }

    /**
     * Map映射集合当中：一组键值对存入【一组元素：Entry】
     * 遍历映射集合：遍历所有的键，遍历所有的值，遍历所有的Entry
     * keySet:获取集合中所有的键
     * values:获取集合中所有的值
     * entrySet:获取集合中所有的Entry
     */
    @Test
    public void testMaps() {
        Map<Object, String> map = new HashMap<>();
        map.put("唐山", "棋子烧饼");
        map.put("邢台", "酸枣");
        map.put("邯郸", "二毛烧鸡");
        map.put("沧州", "火锅鸡");
        //获取所有的键 keySet()
        Set<Object> set = map.keySet();
        //遍历所有的键 增强for循环
        for (Object o : set) {//从Set集合中获取所有的键
            System.out.println("获取所有的键:" + o);
        }
        //2.values() 获取所有的值
        Collection<String> c = map.values();
        //遍历所有值：增强for:获取的集合所有元素
        for (String str : c) {
            System.out.println("获取到的所有值:" + str);
        }
        //3.entrySet() 获取所有的Entry键值
        //返回值：Set<Map.Entry<k,v>>
        //Entry类型：Map.Entry<k,v>
        //Entry存键值的对象 ---Map增加一个针对”键值对“的对象
        //Map.Entry  【Map接口.Entry内部接口对象】获取到所有Entry的方法
        Set<Map.Entry<Object, String>> sets = map.entrySet();
        //获取所有【entry】键值对
        for (Map.Entry<Object, String> s : sets) {
            //System.out.println("所有的entry" + s);
             //Entry中的Key 和 Value 方法：getKey() getValue()
            Object key=s.getKey();
            String value=s.getValue();
            System.out.println("打印Entry中的键和值："+key+" "+value);
        }
    }
    /**
     * forEach(new BiConsumer())
     * BiConsumer 接口 ---封装Entry对象的键与值
     * 作用：遍历出集合中所有的entry【键与值】
     *
     */
    @Test
    public void testForEach(){
        Map<Object, String> map = new HashMap<>();
        map.put("唐山", "棋子烧饼");
        map.put("邢台", "酸枣");
        map.put("邯郸", "二毛烧鸡");
        map.put("沧州", "火锅鸡");
        //forEach()遍历映射集合：键与值
        map.forEach(new BiConsumer<Object,String>(){
            //accept(K,V) 获取entry中所有的键和值
            public void accept(Object o, String s) {
                System.out.println("打印所有的键和值"+o+" "+s);
            }
        });
    }

    /**
     * putIfAbsent()
     * 作用：存一组entry，先判断指定的键是否存在，如果不存在将键值插入
     *                                    如果存在，键值不插入
     *
     */
    @Test
    public void testHashMap(){
        Map<Object, String> map = new HashMap<>();
        map.put("唐山", "棋子烧饼");
        map.put("邢台", "酸枣");
        map.put("邯郸", "二毛烧鸡");
        map.put("沧州", "火锅鸡");
        map.put("唐山","唐顿");
        map.putIfAbsent("石家庄","八大碗");
        map.putIfAbsent("唐山","麻糖");  //相同的键 不插入
        System.out.println("HashMap集合："+map);
    }
}
